#pragma once
#include <iostream>
#include <cstring>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <unistd.h>
using namespace std;

//在这里将获取shmid的参数使用宏定义，免去后面在外部接口处传入
#define defaultsize 4096
#define PATH "./"
#define Projid 'A'

//获取key值
int GetKey()
{
    return ftok(PATH, Projid);
}

//将key值转化为十六进制，与OS一致，方便查看
string ToHex(int key)
{
    char buffer[1024];
    snprintf(buffer, sizeof(buffer), "0X%x", key);
    return buffer;
}

//创建或获取shm的接口，后续会进行封装，sever创建，而client要获取
int CreatShmOrDie(int size, int shmflg)
{
    int key = GetKey();
    int shmid = shmget(key, size, shmflg);
    if (shmid < 0)
    {
        cerr << "shmget fail... errno" << errno << ",fail message: " << strerror(errno) << endl;
    }
    cout << "creat shm success..." << endl;
    return shmid;
}

//secver创建shm
int CreatShm(int size)
{
    return CreatShmOrDie(size, IPC_CREAT | IPC_EXCL | 0666);
}

//client获取shmid
int GetShm(int size)
{
    return CreatShmOrDie(size, IPC_CREAT | 0666);
}

//销毁shm
void DelShm(int shmid)
{
    int ret = shmctl(shmid, IPC_RMID, 0);
    if (ret == -1)
    {
        cerr << "Delete shm fail... errno" << errno << ",fail message: " << strerror(errno) << endl;
    }
    cout << "Delete shm success..." << endl;
}

//进程与shm建立关联关系
void *SetRelationship(int shmid)
{
    void *ptr = shmat(shmid, nullptr, 0);
    if ((long long int)ptr == -1)
    {
        cerr << "process and shm set relationship fail... errno" << errno << ",fail message: " << strerror(errno) << endl;
        return nullptr;
    }
    cout << "process and shm set relationship success..." << endl;
    return ptr;
}

//解除进程与shm的关联关系
void RemoveRelationship(void *addr)
{
    int ret = shmdt(addr);
    if (ret == -1)
    {
        cerr << "remove relationship fail... errno" << errno << ",fail message: " << strerror(errno) << endl;
    }
    else
    {
        cout << "remove relationship success..." << endl;
    }
}